#include "baseline_bagging.h"
#include <math.h>

void baseline_bagging::normalize(double * d, int l) {
	double sum = 0;
	for(int i = 0; i < l; i++) {
		sum += d[i];
	}

	double w = 1 / sum;
	for(int i = 0; i < l; i++) {
		if(d[i] > 0) {
			d[i] *= w;
		}
	}
}

void baseline_bagging::initialize_distribution(double * d, double * y, int l) {
	for(int i = 0; i < l; i++) {
		d[i] = 1;
	}
	normalize(d, l);
}

double baseline_bagging::get_alpha(double * y, double * p, double * d, int l) {
	// alpha is not used anyway.
	return 1;
}

void baseline_bagging::update_distribution(double alpha, double * y, double * p, int l, double * d_t, double * d_t1) {
	for(int i = 0; i < l; i++) {
		if(y[i] == 1) {
			// positive sample
			d_t1[i] = 1;
		} else if (d_t[i] > 0 && p[i] >= 0.5) {
			// negative sample and predicted as positive
			d_t1[i] = 1;
		} else {
			// negative and predicted as negative or does not exit.
			d_t1[i] = 0;
		}
	}
	normalize(d_t1, l);
}

double baseline_bagging::predict(double * alpha, double * p, int n) {
	double sum = 0;
	for(int i = 0; i < n; i++) {
		sum += p[i];
	}
	double f = sum / n;
	return f;
}

bool baseline_bagging::full_updating() {
	return true;
}

string baseline_bagging::get_type() {
	return "baseline_bagging";
}

void baseline_bagging::gradual_update_distribution(double * y, double * p, int l, double * d_t, double * d_t1) {

	int pn = 0;
	for(int i = 0; i < l; i++) {
		if(y[i] == 1) {
			pn ++;
		}
	}

	for(int i = 0; i < l; i++) {
		d_t1[i] = 1;
	}

	int count = 0;
	for(int i = 0; i < l; i++) {
		if(y[i] == 1) {
			d_t1[i] = 1;
		} else if(d_t[i] > 0 && p[i] >= 0.5) {
			d_t1[i] = 1;
			count ++;
			if(count >= pn) {
				break;
			}
		} else {
			d_t1[i] = 0;
		}
	}
	normalize(d_t1, l);
}

//************************

void baseline_gradual_bagging::update_distribution(double alpha, double * y, double * p, int l, double * d_t, double * d_t1) {
	gradual_update_distribution(y, p, l, d_t, d_t1);
}

string baseline_gradual_bagging::get_type() {
	return "baseline_gradual_bagging";
}
